package com.recharge.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.recharge.common.enums.ErrorCode;
import com.recharge.common.result.ResultDO;
import com.recharge.common.result.ResultSupport;
import com.recharge.common.util.BeanUtilsExtends;
import com.recharge.common.util.Constant;
import com.recharge.core.entity.PermissionEntity;
import com.recharge.core.entity.RolePermissionEntity;
import com.recharge.core.mapper.PermissionMapper;
import com.recharge.core.mapper.RolePermissionMapper;
import com.recharge.domain.query.PermissionQueryDO;
import com.recharge.domain.vo.PermissionDO;
import com.recharge.service.PermissionService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.stream.Collectors;

/**
 * <p>
 * 权利 服务实现类
 * </p>
 *
 * @author reagan
 * @since 2020-08-19
 */
@Service
public class PermissionServiceImpl extends ServiceImpl<PermissionMapper, PermissionEntity> implements PermissionService {

    private Logger logger = LoggerFactory.getLogger(this.getClass().getName());

    @Autowired
    private RolePermissionMapper rolePermissionMapper;

    @Transactional(propagation= Propagation.REQUIRED, rollbackFor= Exception.class)
    public ResultDO add(PermissionDO domain) {

        PermissionEntity entity = new PermissionEntity();

        ResultDO result = BeanUtilsExtends.copy(entity, domain);
        if (!result.isSuccess()) {
            logger.debug("error code：" + result.getErrorCode().getCode() + " msg" + result.getErrorCode().getMsg());
            return result;
        }

        entity.setCreateDate(Calendar.getInstance().getTime());
        entity.setModifiDate(entity.getCreateDate());
        entity.setModifier(entity.getCreator());

        boolean res = false;
        try {
            res = this.save(entity);
        } catch(Exception e) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            return result;
        }

        //判断r的值是否小于0.如果小于0 就代表添加失败
        if(!res) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.PERMISSION_ADD_ERROR);
            logger.debug("error code：" + ErrorCode.PERMISSION_ADD_ERROR.getCode() + " msg" + ErrorCode.PERMISSION_ADD_ERROR.getMsg());
            return result;
        }

        PermissionDO resultDomain = getDomain(entity);

        result.setModel(ResultDO.FIRST_MODEL_KEY, resultDomain);

        return result;
    }

    @Transactional(propagation= Propagation.REQUIRED, rollbackFor= Exception.class)
    public ResultDO bindRolePermission(String roleId, String[] permissionIds) {

        ResultDO result = new ResultSupport();

        for(String permissionId : permissionIds) {
            RolePermissionEntity entity = new RolePermissionEntity();
            entity.setRoleId(roleId);
            entity.setPermissionId(permissionId);
            int res = -1;
            try {
                res = rolePermissionMapper.insert(entity);
            } catch (Exception e) {
                result.setSuccess(false);
                result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
                logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg " + ErrorCode.SYSTEM_EXCEPTION.getMsg());
                return result;
            }
            //判断r的值是否小于0.如果小于0 就代表添加失败
            if (res < -1) {
                result.setSuccess(false);
                result.setErrorCode(ErrorCode.PERMISSION_BIND_ROLE_ERROR);
                logger.debug("error code：" + ErrorCode.PERMISSION_BIND_ROLE_ERROR.getCode() + " msg " + ErrorCode.PERMISSION_BIND_ROLE_ERROR.getMsg());
                return result;
            }
        }

        return result;
    }

    @Transactional(propagation= Propagation.REQUIRED, rollbackFor= Exception.class)
    public ResultDO unRolePermissionAll(String roleId) {
        ResultDO result = new ResultSupport();

        QueryWrapper<RolePermissionEntity> queryWrapper = new QueryWrapper<RolePermissionEntity>();
        queryWrapper.eq("role_id", roleId);

        int res = -1;
        try {
            res = rolePermissionMapper.delete(queryWrapper);
        } catch (Exception e) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            return result;
        }

        if(res < 0) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.ROLE_UNBIND_USER_ALL_ERROR);
            logger.debug("error code：" + ErrorCode.ROLE_UNBIND_USER_ALL_ERROR.getCode() + " msg" + ErrorCode.ROLE_UNBIND_USER_ALL_ERROR.getMsg());
            return result;
        }
        return result;
    }

    @Transactional(propagation= Propagation.REQUIRED, rollbackFor= Exception.class)
    public ResultDO edit(PermissionDO domain) {

        PermissionEntity entity = new PermissionEntity();

        ResultDO result = BeanUtilsExtends.copy(entity, domain);
        if (!result.isSuccess()) {
            logger.debug("error code：" + result.getErrorCode().getCode() + " msg" + result.getErrorCode().getMsg());
            return result;
        }

        entity.setModifiDate(Calendar.getInstance().getTime());

        boolean res = false;
        try {
            res = this.updateById(entity);
        } catch (Exception e) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            return result;
        }

        //判断r的值是否小于0.如果小于0 就代表添加失败
        if(!res) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.PERMISSION_EDIT_ERROR);
            logger.debug("error code：" + ErrorCode.PERMISSION_EDIT_ERROR.getCode() + " msg" + ErrorCode.PERMISSION_EDIT_ERROR.getMsg());
            return result;
        }

        return result;
    }

    
    public ResultDO get(String id) {

        ResultDO result = new ResultSupport();
        PermissionEntity entity = null;

        try {
            entity = this.getById(id);
        } catch(Exception e) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            return result;
        }

        PermissionDO domain = getDomain(entity);

        result.setModel(ResultDO.FIRST_MODEL_KEY, domain);

        return result;
    }

    @Transactional(propagation= Propagation.REQUIRED, rollbackFor= Exception.class)
    public ResultDO remove(String id, String modifier) {
        ResultDO result = new ResultSupport();

        PermissionEntity entity = new PermissionEntity();

        entity.setModifiDate(Calendar.getInstance().getTime());
        entity.setModifier(modifier);
        entity.setId(id);
        entity.setIsDelete(Constant.IS_DELETE);

        boolean res = false;
        try {
            res = this.updateById(entity);
        } catch (Exception e) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            return result;
        }

        //判断r的值是否小于0.如果小于0 就代表添加失败
        if(!res) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.PERMISSION_DELETE_ERROR);
            logger.debug("error code：" + ErrorCode.PERMISSION_DELETE_ERROR.getCode() + " msg" + ErrorCode.PERMISSION_DELETE_ERROR.getMsg());
            return result;
        }

        return result;
    }

    public ResultDO getTreeByRoleId(String roleId) {

        ResultDO result = new ResultSupport();

        QueryWrapper<RolePermissionEntity> queryWrapper = new QueryWrapper<RolePermissionEntity>();
        queryWrapper.eq("role_id", roleId);

        List<RolePermissionEntity> list = null;

        try {
            list = this.rolePermissionMapper.selectList(queryWrapper);
        } catch (Exception e) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            return result;
        }
        List<PermissionDO> doList = new ArrayList<>();
        for(RolePermissionEntity entity : list) {
            result = get(entity.getPermissionId());
            if(!result.isSuccess()) {
                logger.debug("error code：" + result.getErrorCode().getCode() + " msg" + result.getErrorCode().getMsg());
                return result;
            }
            doList.add((PermissionDO) result.getModel(ResultDO.FIRST_MODEL_KEY));
        }
        doList = doList.stream().distinct().collect(Collectors.toList());

        //doList = getDomainTree(doList, "");
        result.setModel(ResultDO.FIRST_MODEL_KEY, doList);
        return result;
    }

    public ResultDO getAll(PermissionQueryDO query) {

        ResultDO result = new ResultSupport();

        QueryWrapper<PermissionEntity> queryWrapper = new QueryWrapper<PermissionEntity>();

        queryWrapper.lambda().ne(PermissionEntity::getPermissionId, Constant.MENU);

        //有效的
        queryWrapper.lambda().eq(PermissionEntity::getIsDelete, Constant.IS_DELETE_FALSE);

        List<PermissionEntity> list = null;
        try {
            list = this.baseMapper.selectList(queryWrapper);
        } catch (Exception e) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            return result;
        }

        List<PermissionDO> doList = getDomainList(list);

        if(doList == null) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.PERMISSION_GET_NODE_LIST_ERROR);
            logger.debug("error code：" + ErrorCode.PERMISSION_GET_NODE_LIST_ERROR.getCode() + " msg" + ErrorCode.PERMISSION_GET_NODE_LIST_ERROR.getMsg());
        }
        result.setModel(ResultDO.FIRST_MODEL_KEY, doList);
        return result;
    }

    public ResultDO getTree(PermissionQueryDO query) {

        ResultDO result = new ResultSupport();

        QueryWrapper<PermissionEntity> queryWrapper = new QueryWrapper<PermissionEntity>();
        if(StringUtils.isNotEmpty(query.getId())) {
            queryWrapper.lambda().eq(PermissionEntity::getPermissionId, query.getId());
        } else {
            queryWrapper.lambda().eq(PermissionEntity::getPermissionId, "0");
        }
        
        if(Constant.TREE_TYPE_MENU.equals(query.getQueryType())) {
        	queryWrapper.lambda().eq(PermissionEntity::getType, Constant.MENU);
        }
        if(Constant.BUTT.equals(query.getType())) {
            queryWrapper.lambda().eq(PermissionEntity::getType, Constant.BUTT);
        }
        //有效的
        queryWrapper.lambda().eq(PermissionEntity::getIsDelete, Constant.IS_DELETE_FALSE);

        queryWrapper.lambda().orderByAsc(PermissionEntity::getSort, PermissionEntity::getCreateDate);
        
        List<PermissionEntity> list = null;
        try {
            list = this.baseMapper.selectList(queryWrapper);
        } catch (Exception e) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            return result;
        }

        List<PermissionDO> doList = getNode(list, query.getQueryType(), query.getType());

        if(doList == null) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.PERMISSION_GET_NODE_LIST_ERROR);
            logger.debug("error code：" + ErrorCode.PERMISSION_GET_NODE_LIST_ERROR.getCode() + " msg" + ErrorCode.PERMISSION_GET_NODE_LIST_ERROR.getMsg());
        }
        result.setModel(ResultDO.FIRST_MODEL_KEY, doList);
        return result;
    }


    private List<PermissionDO> getNode(List<PermissionEntity> list, String queryType, String type) {

        ResultDO result = new ResultSupport();

        List<PermissionDO> doList = new ArrayList<>();

        for(PermissionEntity entity : list) {
            QueryWrapper<PermissionEntity> queryWrapper = new QueryWrapper<PermissionEntity>();
            queryWrapper.lambda().eq(PermissionEntity::getPermissionId, entity.getId());
            
            if(Constant.TREE_TYPE_MENU.equals(queryType)) {
            	queryWrapper.lambda().eq(PermissionEntity::getType, Constant.MENU);
            }
            if(Constant.BUTT.equals(type)) {
                queryWrapper.lambda().eq(PermissionEntity::getType, Constant.BUTT);
            }
            //有效的
            queryWrapper.lambda().eq(PermissionEntity::getIsDelete, Constant.IS_DELETE_FALSE);

            queryWrapper.lambda().orderByAsc(PermissionEntity::getSort, PermissionEntity::getCreateDate);
            try {
                list = this.baseMapper.selectList(queryWrapper);
            } catch (Exception e) {
                result.setSuccess(false);
                result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
                logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
                return null;
            }
            PermissionDO domain = getDomain(entity);
            if(list.size() > 0) {
                List<PermissionDO> nodes = getNode(list, queryType, type);
                domain.setNodes(nodes);
            }
            doList.add(domain);
        }

        return doList;
    }

    public ResultDO getPermissionByRoleId(String roleId) {

        ResultDO result = new ResultSupport();

        QueryWrapper<RolePermissionEntity> queryWrapper = new QueryWrapper<RolePermissionEntity>();
        queryWrapper.eq("role_id", roleId);
        List<RolePermissionEntity> list = null;

        try {
            list = this.rolePermissionMapper.selectList(queryWrapper);
        } catch (Exception e) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            return result;
        }

        List<PermissionDO> doList = new ArrayList<>();
        for(RolePermissionEntity entity : list) {
            result  = get(entity.getPermissionId());
            if(!result.isSuccess()) {
                logger.debug("error code：" + result.getErrorCode().getCode() + " msg" + result.getErrorCode().getMsg());
                return result;
            }
            doList.add((PermissionDO) result.getModel(ResultDO.FIRST_MODEL_KEY));
        }
        result.setModel(ResultDO.FIRST_MODEL_KEY, doList);
        return result;
    }
    


	@Override
	public ResultDO getTreeByRoleIds(List<String> roleIds) {
		ResultDO result = new ResultSupport();
		if(roleIds == null || roleIds.isEmpty()) {
	    	return result;
	    }
		List<RolePermissionEntity> list2 = null;
//		try {
//			list2 = rolePermissionMapper.selectList(Wrappers.<RolePermissionEntity>lambdaQuery().in(RolePermissionEntity::getRoleId, roleIds));//selectBatchIds(idList)(roleIds);
//        } catch (Exception e) {
//            result.setSuccess(false);
//            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
//            return result;
//        }

        try {
			list2 = rolePermissionMapper.selectList(null);//selectBatchIds(idList)(roleIds);
        } catch (Exception e) {
            result.setSuccess(false);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            return result;
        }
	   
	      
	    if(list2 == null || list2.isEmpty()) {
	    	return result;
	    }

        list2 = list2.stream().filter( item -> roleIds.contains(item.getRoleId())).collect(Collectors.toList());

        List<String> permissionId = list2.stream().map(RolePermissionEntity::getPermissionId).collect(Collectors.toList());

	    List<PermissionEntity> permissionList = null;
//	    try {
//	    	permissionList = baseMapper.selectBatchIds(list2.stream().map(RolePermissionEntity::getPermissionId).distinct().collect(Collectors.toList()));
//        } catch (Exception e) {
//            result.setSuccess(false);
//            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
//            return result;
//        }

        try {
            permissionList = baseMapper.selectList(Wrappers.<PermissionEntity>lambdaQuery().eq(PermissionEntity::getIsDelete, Constant.IS_DELETE_FALSE).orderByAsc(PermissionEntity::getSort, PermissionEntity::getCreateDate));
        } catch (Exception e) {
            result.setSuccess(false);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            return result;
        }

        permissionList = permissionList.stream().filter( item -> permissionId.contains(item.getId())).collect(Collectors.toList());
	    
	    if(permissionList == null || permissionList.isEmpty()) {
	    	return result;
	    }
	    List<PermissionDO> doList = getDomainList(permissionList);
	    
	    result.setModel(ResultDO.FIRST_MODEL_KEY, doList);
	    
	    return result;
	}



    private PermissionDO getDomain(PermissionEntity entity) {

        //判断房源对象是否为空，为空就返回 空，不为空就进行下面的代码
        if(entity == null) return null;
        PermissionDO domain = new PermissionDO();

        domain = BeanUtilsExtends.copyProperties(domain, entity) ? domain : null;

        //判断拷贝数据到Dto对象是否成功，如果成功则返回domian，如果不成功就返回空
        return domain;
    }

    private List<PermissionDO> getDomainList(List<PermissionEntity> list) {
        //创建一个名为dolist的房源do类型的 list集合
        List<PermissionDO> doList = new ArrayList<PermissionDO>();

        //判断传入的list的集合的size是否大于0
        if(list.size() > 0) {
            //大于0是，遍历list，创建do类型的对象 调用getdomain方法
            for(PermissionEntity entity : list) {

                PermissionDO domain = this.getDomain(entity);

                //判断得到的domain 是否为空 不为空 就往dolist集合里面添加domian 为空就返回空
                if(domain == null) {
                    return null;
                }
                doList.add(domain);
            }
        } else {
            return null;
        }
        return doList;
    }
}
